using DotNetCommon.Expressions.Base;
using DotNetCommon.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace DotNetCommon.Expressions.Visit
{
    /// <summary>
    /// 示例: new Point { X = 1, Y = 2 }
    /// </summary>
    internal class MemberInitVisit : BaseVisit
    {
        protected override void Prepare(ExpressionNode node)
        {
            var memberInitExpression = node.Expression as MemberInitExpression;
            node.Children.Add(new ExpressionNode
            {
                Expression = memberInitExpression.NewExpression,
                Parent = node,
                Children = new List<ExpressionNode>(),
            });
            memberInitExpression.Bindings.ForEach(i => node.Children.Add(new ExpressionNode
            {
                Expression = (i as MemberAssignment).Expression,
                Parent = node,
                Children = new List<ExpressionNode>(),
            }));
        }

        protected override string GenerateFullMarkString(ExpressionNode node)
        {
            var memberInitExpression = node.Expression as MemberInitExpression;
            return $"{node.Children[0].FullMarkString}{node.Children.Skip(1).Select(i => i.FullMarkString).ToStringSeparated(",")}";
        }

        protected override Expression Rebuild(ExpressionNode node)
        {
            var memberInitExpression = node.Expression as MemberInitExpression;
            var inits = new List<MemberAssignment>();
            for (int i = 1; i < node.Children.Count; i++)
            {
                inits.Add((memberInitExpression.Bindings[i - 1] as MemberAssignment).Update(node.Children[i].Expression));
            }
            return memberInitExpression.Update(node.Children[0].Expression as NewExpression, inits);
        }
    }
}
